﻿using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Data.Entity;
using System.Data.Entity.ModelConfiguration.Conventions;
using System.Linq;
using System.Text;

namespace SchoolModel
{
    public class Department
    {
        public Department()
        {
            this.Courses = new HashSet<Course>();
        }
        // Primary key
        public int DepartmentID { get; set; }
        public string Name { get; set; }
        public decimal Budget { get; set; }
        public System.DateTime StartDate { get; set; }
        public int? Administrator { get; set; }

        // Navigation property
        public virtual ICollection<Course> Courses { get; private set; }
    }

    public class Course
    {
        public Course()
        {
            this.StudentGrades = new HashSet<StudentGrade>();
            this.Instructors = new HashSet<Instructor>();
        }
        // Primary key
        public int CourseID { get; set; }

        public string Title { get; set; }
        public int Credits { get; set; }

        // Foreign key
        public int DepartmentID { get; set; }

        // Navigation properties
        public virtual Department Department { get; set; }
        public virtual ICollection<StudentGrade> StudentGrades { get; private set; }
        public virtual ICollection<Instructor> Instructors { get; private set; }
    }

    // Specify that OnlineCourse should be created as a separate table.
    [Table("OnlineCourse")]
    public partial class OnlineCourse : Course
    {
        public string URL { get; set; }
    }

    // Specify that OnsiteCourse should be created as a separate table.
    [Table("OnsiteCourse")]
    public partial class OnsiteCourse : Course
    {
        public string Location { get; set; }
        public string Days { get; set; }
        public System.DateTime Time { get; set; }
    }

    public class Person
    {
        // Primary key
        public int PersonID { get; set; }
        public string LastName { get; set; }
        public string FirstName { get; set; }
    }

    // The Student class will be mapped to the Person table. 
    // The Discriminator column is used to identify what type the rows in the table belong to.
    public class Student : Person
    {
        public Student()
        {
            this.StudentGrades = new HashSet<StudentGrade>();
        }
        public System.DateTime EnrollmentDate { get; set; }
        // Navigation property
        public virtual ICollection<StudentGrade> StudentGrades { get; private set; }
    }

    // The Instructor class will be mapped to the Person table. 
    // The Discriminator column is used to identify what type the rows in the table belong to.
    public class Instructor : Person
    {
        public Instructor()
        {
            this.Courses = new HashSet<Course>();
        }

        public System.DateTime HireDate { get; set; }

        // Navigation properties
        public virtual ICollection<Course> Courses { get; private set; }
        public virtual OfficeAssignment OfficeAssignment { get; set; }
    }

    public class StudentGrade
    {
        // Use the KeyAttribute on the EnrollmentID property, 
        // because we want to override the primary key convention.
        [Key()]
        public int EnrollmentID { get; set; }

        // Foreign key
        public int CourseID { get; set; }
        // Foreign key
        public int StudentID { get; set; }

        public decimal? Grade { get; set; }

        // Navigation properties
        public virtual Course Course { get; set; }
        public virtual Student Student { get; set; }
    }

    public class OfficeAssignment
    {
        // Specifying InstructorID as a primary and foreign key
        // will create a one to zero or one relationship (identifying relationship)
        // between an OfficeAssignment and Instructor tables
        [Key()]
        [ForeignKey("Instructor")]
        public Int32 InstructorID { get; set; }

        public string Location { get; set; }

        // When the Entity Framework sees Timestamp attribute
        // it configures ConcurrencyCheck and DatabaseGeneratedPattern=Computed.
        [Timestamp]
        public Byte[] Timestamp { get; set; }

        // Navigation property
        public virtual Instructor Instructor { get; set; }
    }

    public partial class SchoolEntities : DbContext
    {
        public SchoolEntities()
        {
        }

        public DbSet<Course> Courses { get; set; }
        public DbSet<Department> Departments { get; set; }
        public DbSet<Person> People { get; set; }
        public DbSet<OfficeAssignment> OfficeAssignments { get; set; }
        public DbSet<StudentGrade> StudentGrades { get; set; }

        protected override void OnModelCreating(DbModelBuilder modelBuilder)
        {
            // Tell Code First to ignore PluralizingTableName convention
            // If you keep this convention then the generated tables will have pluralized names.
            modelBuilder.Conventions.Remove<PluralizingTableNameConvention>();
        }
    }

    public class SchoolContextInitializer : DropCreateDatabaseAlways<SchoolEntities>
    {
        protected override void Seed(SchoolEntities context)
        {
            var engineering = new Department { Name = "Engineering", Budget = 350000.00M, StartDate = DateTime.Parse("2007-09-01") };
            context.Departments.Add(engineering);
            var english = new Department { Name = "English", Budget = 120000.00M, StartDate = DateTime.Parse("2007-09-01") };
            context.Departments.Add(english);
            var economics = new Department { Name = "Economics", Budget = 200000.00M, StartDate = DateTime.Parse("2007-09-01") };
            context.Departments.Add(economics);
            var math = new Department { Name = "Mathematics", Budget = 250000.00M, StartDate = DateTime.Parse("2007-09-01") };

            context.Departments.Add(math);

            var courses = new List<Course>
                              {
                                  new OnlineCourse
                                      {
                                          CourseID = 1,
                                          Title = "Poetry",
                                          Credits = 4,
                                          Department = english,
                                          URL = "http://www.fineartschool.net/Poetry"
                                      },
                                  new OnlineCourse
                                      {
                                          CourseID = 2,
                                          Title = "Composition",
                                          Credits = 3,
                                          Department = english,
                                          URL = "http://www.fineartschool.net/Composition"
                                      },
                                  new OnlineCourse
                                      {
                                          CourseID = 3,
                                          Title = "Macroeconomics",
                                          Credits = 4,
                                          Department = economics,
                                          URL = "http://www.fineartschool.net/Poetry"
                                      },
                                  new OnlineCourse
                                      {
                                          CourseID = 4,
                                          Title = "Trigonometry",
                                          Credits = 3,
                                          Department = math,
                                          URL = "http://www.fineartschool.net/Composition"
                                      },
                                  new OnsiteCourse
                                      {
                                          CourseID = 5,
                                          Title = "Chemistry",
                                          Credits = 4,
                                          Department = engineering,
                                          Location = "123 Smith",
                                          Days = "MTWH",
                                          Time = DateTime.Parse("11:30")
                                      },
                                  new OnsiteCourse
                                      {
                                          CourseID = 6,
                                          Title = "Physics",
                                          Credits = 4,
                                          Department = engineering,
                                          Location = "125 Williams",
                                          Days = "TWHF",
                                          Time = DateTime.Parse("13:15")
                                      },
                                  new OnsiteCourse
                                      {
                                          CourseID = 7,
                                          Title = "Calculus",
                                          Credits = 4,
                                          Department = math,
                                          Location = "121 Smith",
                                          Days = "MWHF",
                                          Time = DateTime.Parse("15:30")
                                      },
                                  new OnsiteCourse
                                      {
                                          CourseID = 8,
                                          Title = "Quantitative",
                                          Credits = 4,
                                          Department = math,
                                          Location = "22 Williams",
                                          Days = "TH",
                                          Time = DateTime.Parse("11:15")
                                      },
                              };

            courses.ForEach(c => context.Courses.Add(c));

            // Add instructors to courses.
            courses[0].Instructors.Add(new Instructor { PersonID = 1, LastName = "Abercrombie", FirstName = "Kim", HireDate = DateTime.Parse("1995-03-11") });
            courses[1].Instructors.Add(new Instructor { PersonID = 2, LastName = "Fakhouri", FirstName = "Fadi", HireDate = DateTime.Parse("2002-08-06") });

            new List<Student>
                {
                    new Student
                        {
                            PersonID = 3,
                            LastName = "Barzdukas",
                            FirstName = "Gytis",
                            EnrollmentDate = DateTime.Parse("2005-09-01")
                        },
                    new Student
                        {
                            PersonID = 4,
                            LastName = "Justice",
                            FirstName = "Peggy",
                            EnrollmentDate = DateTime.Parse("2001-08-01")
                        }
                }.ForEach(p => context.People.Add(p));


            new List<StudentGrade>
                {
                    new StudentGrade {EnrollmentID = 1, CourseID = 1, StudentID = 3, Grade = 3.5M},
                    new StudentGrade {EnrollmentID = 2, CourseID = 2, StudentID = 4, Grade = 4.0M}
                }.ForEach(sg => context.StudentGrades.Add(sg));

            new List<OfficeAssignment>
                {
                    new OfficeAssignment {InstructorID = 1, Location = "17 Smith"},
                    new OfficeAssignment {InstructorID = 2, Location = "29 Adams"}
                }.ForEach(oa => context.OfficeAssignments.Add(oa));

            context.SaveChanges();
        }
    }


}
